package com.ikas.ai.server.module.flow.listener;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.ikas.ai.framework.core.event.NodeEvent;
import com.ikas.ai.framework.core.listener.NodeListener;
import com.ikas.ai.framework.core.model.BatchDataFunction;
import com.ikas.ai.framework.flow.ScoreFlow;
import com.ikas.ai.framework.node.Node;
import com.ikas.ai.framework.node.NodeStatus;
import com.ikas.ai.server.error.BusinessException;
import com.ikas.ai.server.module.flow.model.FlowLog;
import com.ikas.ai.server.module.flow.service.FlowLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.Objects;

/**
 * @Description: 流程节点日志
 * @Author: qi.yilai
 * @Date: 2023/2/1 17:10
 * @Version: 1.0.0
 **/
@Component
public class MaintainNodeLogListener implements NodeListener {
    private static final String FAILURE_LOG = "【%s】执行失败，异常：%s";
    private static final String SUCCESS_DEFAULT_LOG = "【%s】执行成功";
    private static final String SUCCESS_RESULT_LOG = "，输出结果：%s";
    private static final String START_DEFAULT_LOG = "【%s】开始执行";
    private static final String SUCCESS_WARNING_LOG = "，警告：%s";

    @Autowired
    private FlowLogService flowLogService;

    @Override
    public boolean fireEvent(NodeEvent event) {
        Node node = event.getOwner();
        ScoreFlow scoreFlow = node.getOwner();

        FlowLog flowLog = new FlowLog();
        flowLog.setSceneId(scoreFlow.getSceneId());
        flowLog.setFlowId(scoreFlow.getFlowId());
        flowLog.setFlowInstanceId(scoreFlow.getFlowInstanceId());
        flowLog.setLogType((byte)1); // 1=流程节点
        flowLog.setNodeId(node.nodeId());
        flowLog.setNodeInstanceId(node.nodeInstanceId());

        NodeStatus status = node.status();
        flowLog.setStatus(status.getStatus().byteValue());
        if (status == NodeStatus.CREATED) {
            return true;
        }
        String log;
        switch (status) {
            case STARTING:
                log = String.format(START_DEFAULT_LOG, node.name());
                break;
            case SUCCESS:
                log = successLog(node);
                Object result = node.result();
                String resultTxt;
                if (result instanceof JSONObject) {
                    resultTxt = JSONObject.toJSONString(result, SerializerFeature.WriteBigDecimalAsPlain, SerializerFeature.WriteMapNullValue);
                } else if (result instanceof BatchDataFunction){
                    resultTxt = JSONObject.toJSONString(result);
                } else {
                    resultTxt = result.toString();
                }
                flowLog.setResult(resultTxt);
                flowLog.setInputParam(JSONObject.toJSONString(node.previous(), SerializerFeature.WriteBigDecimalAsPlain, SerializerFeature.WriteMapNullValue));
                break;
            case FAILURE:
                log = String.format(FAILURE_LOG, node.name(), node.exception());
                break;
            default:
                throw new BusinessException("不支持其他流程节点状态");
        }
        flowLog.setLog(log);
        flowLog.setCreateTime(new Date());
        flowLogService.save(flowLog);
        return true;
    }

    private String successLog(Node node) {
        Object result = node.result();
        String log = String.format(SUCCESS_DEFAULT_LOG, node.name());
        if (result instanceof JSONObject) {
            log += String.format(SUCCESS_RESULT_LOG, JSONObject.toJSONString(result, SerializerFeature.WriteBigDecimalAsPlain, SerializerFeature.WriteMapNullValue));
        } else if (result instanceof Boolean) {
            log += String.format(SUCCESS_RESULT_LOG, result);
        }
        if (Objects.nonNull(node.warningMessage())) {
            log += String.format(SUCCESS_WARNING_LOG, node.warningMessage());
        }
        return log;
    }
}
